#ifndef __MS518XN_H__
#define __MS518XN_H__

#define MS518XN_CHANNEL(num) { \
		.type = IIO_VOLTAGE, \
		.indexed = 1, \
		.channel = num, \
		.address = num, \
		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
		.scan_index = num, \
		.scan_type = { \
			.sign = 's', \
			.realbits = 16, \
			.storagebits = 16, \
			.endianness = IIO_CPU, \
		}, \
}

#define MS518XN_BIT_COVER ((0x01) << 13)
#define MS518XN_BIT_INCC(x) ((x & 0x7) << 10)
#define MS518XN_BIT_INX(x) ((x & 0x7) << 7)
#define MS518XN_BIT_BW(x) ((x & 0x1) << 6)
#define MS518XN_BIT_REF(x) ((x & 0x7) << 3)
#define MS518XN_BIT_SEQ(x) ((x & 0x3) << 1)
#define MS518XN_BIT_RB(x) (x & 0x1)

#define MS518XN_CFG_MASK 0x3fff
#define MS518XN_CFG_WR(cfg, BIT, x) ((cfg & (~BIT(0xffff))) | BIT(x))
#define MS518XN_CFG_RD_REF(x) ((x >> 3) & 0x7)

typedef enum {
	MS5182N,
	MS5189N,
} ms518xn_e;

typedef enum {
	MS518XN_USE_SPI_PHY,
} ms518xn_phy_type_e;

typedef enum {
	// 双极性差分对
	MS518XN_INCC_BIPOLDA = 0x00,
	// 双极性
	MS518XN_INCC_BIPOL = 0x02,
	// 温度传感器
	MS518XN_INCC_THERMAL = 0x03,
	// 单极性差分对
	MS518XN_INCC_UNIPOLDA = 0x04,
	// 单极性
	MS518XN_INCC_UNIPOL = 0x06,
	// 单极性，INx 以 GND 为参考
	MS518XN_INCC_UNIPOLGND = 0x07,
} ms518xn_incc_e;

typedef enum {
	MS518XN_BANDWITDH_QUARTER = 0,
	MS518XN_BANDWITDH_FULL = 1,
} ms518xn_bw_e;

typedef enum {
	// 内部基准电压源 2.5V
	MS518XN_REF_INNER_25 = 0x00,
	// 内部基准电压源 4.096V
	MS518XN_REF_INNER_4096 = 0x01,
	// 外部基准电压源，使能温度传感器
	MS518XN_REF_EXTENTH = 0x02,
	// 外部基准电压源，使能温度传感器、内部缓冲器
	MS518XN_REF_EXTENTHBUF = 0x03,
	// 外部基准电压源，禁用温度传感器
	MS518XN_REF_EXTDETH = 0x06,
	// 外部基准电压源，禁用温度传感器、内部缓冲器
	MS518XN_REF_EXTDETHBUF = 0x07,
} ms518xn_ref_e;

typedef enum {
	// 禁用序列器
	MS518XN_SEQ_DISABLE = 0x00,
	// 序列扫描期间更新配置
	MS518XN_SEQ_UPADTE = 0x01,
	// 扫描IN0-INX（由set_channel控制），然后扫描温度
	MS518XN_SEQ_INXTH = 0x02,
	// 扫描IN0-INX（由set_channel控制）
	MS518XN_SEQ_INX = 0x03,
} ms518xn_seq_e;

typedef enum {
	MS518XN_RB_ENABLE = 0x00,
	MS518XN_RB_DISABLE = 0x01,
} ms518xn_rb_e;

typedef struct ms518xn_phy_s ms518xn_phy_t;
typedef struct ms518xn_chip_s ms518xn_chip_t;
typedef struct ms518xn_s ms518xn_t;

struct ms518xn_phy_s {
	void* phy;
	int (* reset)(ms518xn_phy_t*);
	int (* transfer)(ms518xn_phy_t*, uint16_t*, uint16_t*);
};

struct ms518xn_chip_s {
	uint16_t cfg_stash;
	uint16_t cfg_commit;
	ms518xn_phy_t phy;
	int (* sync)(ms518xn_chip_t*);
	int (* send)(ms518xn_chip_t*);
	int (* set_incc)(ms518xn_chip_t*, ms518xn_incc_e);
	int (* set_inx)(ms518xn_chip_t*, uint8_t);
	int (* set_bw)(ms518xn_chip_t*, ms518xn_bw_e);
	int (* set_ref)(ms518xn_chip_t*, ms518xn_ref_e);
	int (* set_seq)(ms518xn_chip_t*, ms518xn_seq_e);
	int (* set_rb)(ms518xn_chip_t*, ms518xn_rb_e);
};

struct ms518xn_s {
	ms518xn_chip_t chip;
	ms518xn_e type;
};

int ms518xn_probe(struct iio_dev* dev, struct device_node* node,
		ms518xn_phy_type_e type, void* phy);

#endif

